//! # 消息总线指标收集
//!
//! 提供消息总线系统的指标收集、监控和报告功能

use std::collections::HashMap;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use tokio::sync::RwLock;

use crate::error::{MessageBusError, MessageBusResult};
use crate::message::Message;

/// 指标类型
#[derive(Debug, Clone, PartialEq)]
pub enum MetricType {
    /// 计数器 - 单调递增
    Counter,
    /// 仪表盘 - 可增可减
    Gauge,
    /// 直方图 - 记录分布
    Histogram,
    /// 摘要 - 记录分位数
    Summary,
}

/// 指标值
#[derive(Debug, Clone)]
pub enum MetricValue {
    Counter(u64),
    Gauge(f64),
    Histogram(Vec<f64>),
    Summary { count: u64, sum: f64, quantiles: HashMap<f64, f64> },
}

/// 指标标签
pub type MetricLabels = HashMap<String, String>;

/// 指标数据点
#[derive(Debug, Clone)]
pub struct MetricPoint {
    /// 指标名称
    pub name: String,
    /// 指标类型
    pub metric_type: MetricType,
    /// 指标值
    pub value: MetricValue,
    /// 标签
    pub labels: MetricLabels,
    /// 时间戳
    pub timestamp: chrono::DateTime<chrono::Utc>,
    /// 帮助信息
    pub help: Option<String>,
}

/// 消息总线指标收集器
#[derive(Debug)]
pub struct MessageBusMetrics {
    /// 计数器指标
    counters: Arc<RwLock<HashMap<String, Arc<AtomicU64>>>>,
    /// 仪表盘指标
    gauges: Arc<RwLock<HashMap<String, Arc<parking_lot::RwLock<f64>>>>>,
    /// 直方图指标
    histograms: Arc<RwLock<HashMap<String, Arc<RwLock<Vec<f64>>>>>>,
    /// 指标标签
    labels: Arc<RwLock<HashMap<String, MetricLabels>>>,
    /// 指标帮助信息
    help_texts: Arc<RwLock<HashMap<String, String>>>,
    /// 是否启用
    enabled: bool,
}

impl Default for MessageBusMetrics {
    fn default() -> Self {
        Self::new()
    }
}

impl MessageBusMetrics {
    /// 创建新的指标收集器
    pub fn new() -> Self {
        Self {
            counters: Arc::new(RwLock::new(HashMap::new())),
            gauges: Arc::new(RwLock::new(HashMap::new())),
            histograms: Arc::new(RwLock::new(HashMap::new())),
            labels: Arc::new(RwLock::new(HashMap::new())),
            help_texts: Arc::new(RwLock::new(HashMap::new())),
            enabled: true,
        }
    }

    /// 创建禁用的指标收集器
    pub fn disabled() -> Self {
        let mut metrics = Self::new();
        metrics.enabled = false;
        metrics
    }

    /// 检查是否启用
    pub fn is_enabled(&self) -> bool {
        self.enabled
    }

    /// 启用指标收集
    pub fn enable(&mut self) {
        self.enabled = true;
    }

    /// 禁用指标收集
    pub fn disable(&mut self) {
        self.enabled = false;
    }

    /// 注册计数器指标
    pub async fn register_counter(
        &self,
        name: impl Into<String>,
        help: impl Into<String>,
        labels: MetricLabels,
    ) -> MessageBusResult<()> {
        if !self.enabled {
            return Ok(());
        }

        let name = name.into();
        let help = help.into();

        let mut counters = self.counters.write().await;
        let mut help_texts = self.help_texts.write().await;
        let mut label_map = self.labels.write().await;

        if !counters.contains_key(&name) {
            counters.insert(name.clone(), Arc::new(AtomicU64::new(0)));
            help_texts.insert(name.clone(), help);
            label_map.insert(name, labels);
        }

        Ok(())
    }

    /// 注册仪表盘指标
    pub async fn register_gauge(
        &self,
        name: impl Into<String>,
        help: impl Into<String>,
        labels: MetricLabels,
    ) -> MessageBusResult<()> {
        if !self.enabled {
            return Ok(());
        }

        let name = name.into();
        let help = help.into();

        let mut gauges = self.gauges.write().await;
        let mut help_texts = self.help_texts.write().await;
        let mut label_map = self.labels.write().await;

        if !gauges.contains_key(&name) {
            gauges.insert(name.clone(), Arc::new(parking_lot::RwLock::new(0.0)));
            help_texts.insert(name.clone(), help);
            label_map.insert(name, labels);
        }

        Ok(())
    }

    /// 注册直方图指标
    pub async fn register_histogram(
        &self,
        name: impl Into<String>,
        help: impl Into<String>,
        labels: MetricLabels,
    ) -> MessageBusResult<()> {
        if !self.enabled {
            return Ok(());
        }

        let name = name.into();
        let help = help.into();

        let mut histograms = self.histograms.write().await;
        let mut help_texts = self.help_texts.write().await;
        let mut label_map = self.labels.write().await;

        if !histograms.contains_key(&name) {
            histograms.insert(name.clone(), Arc::new(RwLock::new(Vec::new())));
            help_texts.insert(name.clone(), help);
            label_map.insert(name, labels);
        }

        Ok(())
    }

    /// 增加计数器
    pub async fn increment_counter(&self, name: &str, value: u64) -> MessageBusResult<()> {
        if !self.enabled {
            return Ok(());
        }

        let counters = self.counters.read().await;
        if let Some(counter) = counters.get(name) {
            counter.fetch_add(value, Ordering::Relaxed);
            Ok(())
        } else {
            Err(MessageBusError::internal_error(format!("计数器指标不存在: {}", name)))
        }
    }

    /// 设置仪表盘值
    pub async fn set_gauge(&self, name: &str, value: f64) -> MessageBusResult<()> {
        if !self.enabled {
            return Ok(());
        }

        let gauges = self.gauges.read().await;
        if let Some(gauge) = gauges.get(name) {
            *gauge.write() = value;
            Ok(())
        } else {
            Err(MessageBusError::internal_error(format!("仪表盘指标不存在: {}", name)))
        }
    }

    /// 增加仪表盘值
    pub async fn add_gauge(&self, name: &str, value: f64) -> MessageBusResult<()> {
        if !self.enabled {
            return Ok(());
        }

        let gauges = self.gauges.read().await;
        if let Some(gauge) = gauges.get(name) {
            *gauge.write() += value;
            Ok(())
        } else {
            Err(MessageBusError::internal_error(format!("仪表盘指标不存在: {}", name)))
        }
    }

    /// 观察直方图值
    pub async fn observe_histogram(&self, name: &str, value: f64) -> MessageBusResult<()> {
        if !self.enabled {
            return Ok(());
        }

        let histograms = self.histograms.read().await;
        if let Some(histogram) = histograms.get(name) {
            let mut hist = histogram.write().await;
            hist.push(value);
            
            // 限制历史数据大小，保留最近的1000个值
            let len = hist.len();
            if len > 1000 {
                hist.drain(0..len - 1000);
            }
            
            Ok(())
        } else {
            Err(MessageBusError::internal_error(format!("直方图指标不存在: {}", name)))
        }
    }

    /// 获取所有指标
    pub async fn get_all_metrics(&self) -> Vec<MetricPoint> {
        if !self.enabled {
            return Vec::new();
        }

        let mut metrics = Vec::new();
        let timestamp = chrono::Utc::now();

        // 获取计数器指标
        let counters = self.counters.read().await;
        let labels = self.labels.read().await;
        let help_texts = self.help_texts.read().await;

        for (name, counter) in counters.iter() {
            let value = counter.load(Ordering::Relaxed);
            let metric_labels = labels.get(name).cloned().unwrap_or_default();
            let help = help_texts.get(name).cloned();

            metrics.push(MetricPoint {
                name: name.clone(),
                metric_type: MetricType::Counter,
                value: MetricValue::Counter(value),
                labels: metric_labels,
                timestamp,
                help,
            });
        }

        // 获取仪表盘指标
        let gauges = self.gauges.read().await;
        for (name, gauge) in gauges.iter() {
            let value = *gauge.read();
            let metric_labels = labels.get(name).cloned().unwrap_or_default();
            let help = help_texts.get(name).cloned();

            metrics.push(MetricPoint {
                name: name.clone(),
                metric_type: MetricType::Gauge,
                value: MetricValue::Gauge(value),
                labels: metric_labels,
                timestamp,
                help,
            });
        }

        // 获取直方图指标
        let histograms = self.histograms.read().await;
        for (name, histogram) in histograms.iter() {
            let hist = histogram.read().await;
            let values = hist.clone();
            let metric_labels = labels.get(name).cloned().unwrap_or_default();
            let help = help_texts.get(name).cloned();

            metrics.push(MetricPoint {
                name: name.clone(),
                metric_type: MetricType::Histogram,
                value: MetricValue::Histogram(values),
                labels: metric_labels,
                timestamp,
                help,
            });
        }

        metrics
    }

    /// 获取 Prometheus 格式的指标
    pub async fn get_prometheus_metrics(&self) -> String {
        if !self.enabled {
            return String::new();
        }

        let metrics = self.get_all_metrics().await;
        let mut output = String::new();

        for metric in metrics {
            // 添加帮助信息
            if let Some(help) = &metric.help {
                output.push_str(&format!("# HELP {} {}\n", metric.name, help));
            }

            // 添加类型信息
            let type_str = match metric.metric_type {
                MetricType::Counter => "counter",
                MetricType::Gauge => "gauge",
                MetricType::Histogram => "histogram",
                MetricType::Summary => "summary",
            };
            output.push_str(&format!("# TYPE {} {}\n", metric.name, type_str));

            // 格式化标签
            let labels_str = if metric.labels.is_empty() {
                String::new()
            } else {
                let label_pairs: Vec<String> = metric.labels
                    .iter()
                    .map(|(k, v)| format!("{}=\"{}\"", k, v))
                    .collect();
                format!("{{{}}}", label_pairs.join(","))
            };

            // 添加指标值
            match metric.value {
                MetricValue::Counter(value) => {
                    output.push_str(&format!("{}{} {}\n", metric.name, labels_str, value));
                }
                MetricValue::Gauge(value) => {
                    output.push_str(&format!("{}{} {}\n", metric.name, labels_str, value));
                }
                MetricValue::Histogram(values) => {
                    if !values.is_empty() {
                        // 计算分位数
                        let mut sorted_values = values;
                        sorted_values.sort_by(|a, b| a.partial_cmp(b).unwrap());
                        
                        let count = sorted_values.len();
                        let sum: f64 = sorted_values.iter().sum();
                        
                        // 输出直方图统计
                        output.push_str(&format!("{}_count{} {}\n", metric.name, labels_str, count));
                        output.push_str(&format!("{}_sum{} {}\n", metric.name, labels_str, sum));
                        
                        // 输出分位数
                        let percentiles = [0.5, 0.9, 0.95, 0.99];
                        for &p in &percentiles {
                            let index = ((count as f64 * p) as usize).min(count - 1);
                            let value = sorted_values[index];
                            output.push_str(&format!(
                                "{}_quantile{{quantile=\"{}\"{}}}{} {}\n",
                                metric.name,
                                p,
                                if labels_str.is_empty() { "" } else { &format!(",{}", &labels_str[1..labels_str.len()-1]) },
                                if labels_str.is_empty() { "" } else { "}" },
                                value
                            ));
                        }
                    }
                }
                MetricValue::Summary { count, sum, quantiles } => {
                    output.push_str(&format!("{}_count{} {}\n", metric.name, labels_str, count));
                    output.push_str(&format!("{}_sum{} {}\n", metric.name, labels_str, sum));
                    
                    for (&quantile, &value) in &quantiles {
                        output.push_str(&format!(
                            "{}_quantile{{quantile=\"{}\"{}}}{} {}\n",
                            metric.name,
                            quantile,
                            if labels_str.is_empty() { "" } else { &format!(",{}", &labels_str[1..labels_str.len()-1]) },
                            if labels_str.is_empty() { "" } else { "}" },
                            value
                        ));
                    }
                }
            }

            output.push('\n');
        }

        output
    }

    /// 清空所有指标
    pub async fn clear(&self) {
        if !self.enabled {
            return;
        }

        let mut counters = self.counters.write().await;
        let mut gauges = self.gauges.write().await;
        let mut histograms = self.histograms.write().await;
        let mut labels = self.labels.write().await;
        let mut help_texts = self.help_texts.write().await;

        counters.clear();
        gauges.clear();
        histograms.clear();
        labels.clear();
        help_texts.clear();
    }
}

/// 消息总线指标初始化器
pub struct MessageBusMetricsInitializer;

impl MessageBusMetricsInitializer {
    /// 初始化标准指标
    pub async fn initialize_standard_metrics(metrics: &MessageBusMetrics) -> MessageBusResult<()> {
        // 消息发布指标
        metrics.register_counter(
            "rustcloud_bus_messages_published_total",
            "消息总线发布的消息总数",
            HashMap::new(),
        ).await?;

        // 消息接收指标
        metrics.register_counter(
            "rustcloud_bus_messages_received_total",
            "消息总线接收的消息总数",
            HashMap::new(),
        ).await?;

        // 消息失败指标
        metrics.register_counter(
            "rustcloud_bus_messages_failed_total",
            "消息总线失败的消息总数",
            HashMap::new(),
        ).await?;

        // 活跃订阅者数量
        metrics.register_gauge(
            "rustcloud_bus_active_subscribers",
            "当前活跃的订阅者数量",
            HashMap::new(),
        ).await?;

        // 活跃主题数量
        metrics.register_gauge(
            "rustcloud_bus_active_topics",
            "当前活跃的主题数量",
            HashMap::new(),
        ).await?;

        // 消息大小分布
        metrics.register_histogram(
            "rustcloud_bus_message_size_bytes",
            "消息大小分布（字节）",
            HashMap::new(),
        ).await?;

        // 消息处理延迟
        metrics.register_histogram(
            "rustcloud_bus_message_processing_duration_ms",
            "消息处理延迟分布（毫秒）",
            HashMap::new(),
        ).await?;

        // 队列长度
        metrics.register_gauge(
            "rustcloud_bus_queue_length",
            "消息队列长度",
            HashMap::new(),
        ).await?;

        Ok(())
    }
}

/// 记录消息发布指标
pub async fn record_publish_metrics(
    metrics: &MessageBusMetrics,
    message: &Message,
    success: bool,
    duration_ms: f64,
) {
    if !metrics.is_enabled() {
        return;
    }

    // 记录发布总数
    let _ = metrics.increment_counter("rustcloud_bus_messages_published_total", 1).await;

    // 记录消息大小
    let message_size = message.size() as f64;
    let _ = metrics.observe_histogram("rustcloud_bus_message_size_bytes", message_size).await;

    // 记录处理延迟
    let _ = metrics.observe_histogram("rustcloud_bus_message_processing_duration_ms", duration_ms).await;

    if success {
        let _ = metrics.increment_counter("rustcloud_bus_messages_received_total", 1).await;
    } else {
        let _ = metrics.increment_counter("rustcloud_bus_messages_failed_total", 1).await;
    }
}

/// 更新订阅者指标
pub async fn update_subscriber_metrics(
    metrics: &MessageBusMetrics,
    active_subscribers: usize,
    active_topics: usize,
    queue_length: usize,
) {
    if !metrics.is_enabled() {
        return;
    }

    let _ = metrics.set_gauge("rustcloud_bus_active_subscribers", active_subscribers as f64).await;
    let _ = metrics.set_gauge("rustcloud_bus_active_topics", active_topics as f64).await;
    let _ = metrics.set_gauge("rustcloud_bus_queue_length", queue_length as f64).await;
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_metrics_registration() {
        let metrics = MessageBusMetrics::new();

        // 注册计数器
        assert!(metrics.register_counter(
            "test_counter",
            "测试计数器",
            HashMap::new()
        ).await.is_ok());

        // 注册仪表盘
        assert!(metrics.register_gauge(
            "test_gauge",
            "测试仪表盘",
            HashMap::new()
        ).await.is_ok());

        // 注册直方图
        assert!(metrics.register_histogram(
            "test_histogram",
            "测试直方图",
            HashMap::new()
        ).await.is_ok());
    }

    #[tokio::test]
    async fn test_metrics_operations() {
        let metrics = MessageBusMetrics::new();

        // 注册指标
        metrics.register_counter("test_counter", "测试", HashMap::new()).await.unwrap();
        metrics.register_gauge("test_gauge", "测试", HashMap::new()).await.unwrap();
        metrics.register_histogram("test_histogram", "测试", HashMap::new()).await.unwrap();

        // 操作计数器
        assert!(metrics.increment_counter("test_counter", 5).await.is_ok());

        // 操作仪表盘
        assert!(metrics.set_gauge("test_gauge", 42.0).await.is_ok());
        assert!(metrics.add_gauge("test_gauge", 8.0).await.is_ok());

        // 操作直方图
        assert!(metrics.observe_histogram("test_histogram", 1.5).await.is_ok());
        assert!(metrics.observe_histogram("test_histogram", 2.5).await.is_ok());
    }

    #[tokio::test]
    async fn test_prometheus_export() {
        let metrics = MessageBusMetrics::new();

        // 注册并操作指标
        metrics.register_counter("test_counter", "测试计数器", HashMap::new()).await.unwrap();
        metrics.increment_counter("test_counter", 10).await.unwrap();

        // 导出 Prometheus 格式
        let prometheus_output = metrics.get_prometheus_metrics().await;
        assert!(prometheus_output.contains("test_counter"));
        assert!(prometheus_output.contains("10"));
    }

    #[tokio::test]
    async fn test_disabled_metrics() {
        let metrics = MessageBusMetrics::disabled();
        assert!(!metrics.is_enabled());

        // 禁用状态下所有操作都应该成功但不做任何事
        assert!(metrics.register_counter("test", "test", HashMap::new()).await.is_ok());
        assert!(metrics.increment_counter("test", 1).await.is_ok());

        let prometheus_output = metrics.get_prometheus_metrics().await;
        assert!(prometheus_output.is_empty());
    }
}